﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Windows.Forms;
using GerbilLib;

namespace MediaGerbil
{
    /// <summary>
    /// The ImagePicker dialog displays all images available on TMDb for a given MediaItem or a message
    /// if there are no images available.
    /// </summary>
    public partial class ImagePicker : Form
    {
        /// <summary>
        /// Gets or sets the media item for which to show images.
        /// </summary>
        /// <value>
        /// The media item.
        /// </value>
        private MediaItem MediaItem { get; set; }
        /// <summary>
        /// Gets or sets the TMDb item containing all available images for the media item.
        /// </summary>
        /// <value>
        /// The TMDb item.
        /// </value>
        private TmdbItem TmdbItem { get; set; }
        /// <summary>
        /// Gets or sets the selected image preview object.
        /// </summary>
        /// <value>
        /// The selected image preview object.
        /// </value>
        private HashSet<ImagePreview> SelectedImagePreview { get; set; }
        /// <summary>
        /// Gets or sets the cover image options.
        /// </summary>
        /// <value>
        /// The cover image options.
        /// </value>
        private CoverImageOptions CoverImageOptions { get; set; }

        private bool UseBackdropImages { get; set; }
        private List<TmdbImageSet> TmdbImageSet { get; set; }
        private bool IsDownloading { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="ImagePicker"/> class.
        /// </summary>
        /// <param name="item">The MediaItem for which to show images.</param>
        /// <param name="coverImageOptions">The cover image options.</param>
        public ImagePicker(MediaItem item, CoverImageOptions coverImageOptions, bool useBackdropImages = false)
        {
            MediaItem = item;
            CoverImageOptions = coverImageOptions;
            UseBackdropImages = useBackdropImages;
            SelectedImagePreview = new HashSet<ImagePreview>();
            TmdbItem = TmdbScraper.MovieImdbLookup(ConfigurationManager.AppSettings["TmdbApiKey"], MediaItem.ImdbId);
            if (TmdbItem != null) TmdbImageSet = UseBackdropImages ? TmdbItem.Backdrops : TmdbItem.Posters;
            InitializeComponent();
        }

        /// <summary>
        /// Handles the Shown event of the ImagePicker control. Populates the flow layout panel with images.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ImagePicker_Shown(object sender, EventArgs e)
        {
            if (TmdbItem == null)
            {
                label.Text = string.Format(label.Text, MediaItem.Title);
                label.Visible = true;
                btnOk.Enabled = false;
            }
            else
                foreach (TmdbImageSet imageSet in TmdbImageSet)
                {
                    TmdbImage image = GetPreviewImage(imageSet);
                    ImagePreview preview = new ImagePreview(image, imageSet, UseBackdropImages ? CoverImageOptions.BackdropImageDefaultSize : CoverImageOptions.CoverImageDefaultSize);
                    preview.Click += new EventHandler(ImagePreview_Click);
                    flowLayoutPanel.Controls.Add(preview);
                }
        }

        /// <summary>
        /// Handles the Click event of the ImagePreview control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ImagePreview_Click(object sender, EventArgs e)
        {
            if (IsDownloading) return;

            ImagePreview box = (ImagePreview)sender;
            if (SelectedImagePreview.Count > 0 && (!UseBackdropImages || ModifierKeys != Keys.Control))
            {
                foreach (ImagePreview imagePreview in SelectedImagePreview)
                    imagePreview.BackColor = System.Drawing.SystemColors.Control;
                SelectedImagePreview.Clear();
            }
            
            if (SelectedImagePreview.Contains(box))
            {
                box.BackColor = System.Drawing.SystemColors.Control;
                SelectedImagePreview.Remove(box);
            }
            else
            {
                box.BackColor = System.Drawing.Color.Red;
                SelectedImagePreview.Add(box);
            }

            btnOk.Enabled = SelectedImagePreview.Count > 0;
        }

        /// <summary>
        /// Handles the Click event of the btnOk control. Saves the selected image to the folder and closes the dialog.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private async void btnOk_Click(object sender, EventArgs e)
        {
            if (SelectedImagePreview.Count > 0)
            {
                // Since we have the info available store TMDb ID in Media Item
                // TODO: Should be done by a proper TMDb scraper in the future
                MediaItem.TmdbId = TmdbItem.TmdbId.ToString();

                Cursor = Cursors.WaitCursor;
                btnOk.Enabled = false;
                btnOk.Text = string.Format("Downloading Image{0}...", SelectedImagePreview.Count > 1 ? "s" : string.Empty);
                
                // Download all selected images
                IsDownloading = true;
                foreach(ImagePreview imagePreview in SelectedImagePreview)
                {
                    TmdbImage selectedImageSize = imagePreview.SelectedImageSize;
                    if (UseBackdropImages)
                        await TaskManager.Run("Download Backdrop Image to Folder", () => TmdbScraper.SaveBackdropImageToFolder(MediaItem, selectedImageSize));
                    else
                        await TaskManager.Run("Download Cover Image to Folder", () => TmdbScraper.SaveCoverImageToFolder(MediaItem, selectedImageSize));
                }
                
                Close();
            }
        }

        /// <summary>
        /// Handles the Click event of the btnCancel control. Closes the dialog without making any changes.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            Close();
        }

        /// <summary>
        /// Gets the preview image from the given image set.
        /// </summary>
        /// <param name="imageSet">The TMDb image set.</param>
        /// <returns>TMDb image for the selected size.</returns>
        private TmdbImage GetPreviewImage(TmdbImageSet imageSet)
        {
            switch (UseBackdropImages ? CoverImageOptions.BackdropImagePreviewSize : CoverImageOptions.CoverImagePreviewSize)
            {
                case TmdbImage.ImageSize.Thumb: return imageSet.Thumb;
                case TmdbImage.ImageSize.w154: return imageSet.W154;
                case TmdbImage.ImageSize.Cover: return imageSet.Cover;
                case TmdbImage.ImageSize.w342: return imageSet.W342;
                case TmdbImage.ImageSize.Mid: return imageSet.Mid;
                default: return imageSet.Thumb;
            }
        }

        /// <summary>
        /// Determines whether there more than one image available. Used to decide whether the dialog
        /// should be shown or not based on setting in Preferences.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if there is more than one image available; otherwise, <c>false</c>.
        /// </returns>
        public bool HasMoreThanOneImageAvailable()
        {
            return TmdbItem != null && TmdbImageSet.Count > 1;
        }

        /// <summary>
        /// Saves the first cover image in the TMDb image collection to the media item folder. Typically
        /// used when the image picker dialog is not shown but an automatic choice is made.
        /// </summary>
        /// <returns><c>true</c> if the image was successfully downloaded and saved, otherwise <c>false</c>.</returns>
        public bool SaveFirstCoverImageToFolder()
        {
            if (TmdbItem == null || TmdbImageSet.Count == 0) return false;
            return TmdbScraper.SaveCoverImageToFolder(MediaItem, TmdbImageSet[0]);
        }
    }
}
